package se.robertfoss.ChanImageBrowser.Fetcher;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;

import se.robertfoss.ChanImageBrowser.ImageHandler;
import se.robertfoss.ChanImageBrowser.Viewer;
import android.os.AsyncTask;
import android.os.Process;
import android.util.Log;

public class FetcherManager extends AsyncTask<String, Void, Void> {

	private HashMap<String, Boolean> visitedUrls;
	private LinkedList<String> imageUrlList;
	private LinkedList<String> linkUrlList;

	private IndexFetcher indexfetcher;
	private ArrayList<ImageFetcher> imagefetchers;
	private ArrayList<ThreadFetcher> threadfetchers;

	private volatile boolean initialized = false;
	private final int MAX_IMAGEFETCHERS = 3;
	private final int MAX_THREADFETCHERS = 1;
	private ImageHandler imageHandler;
	private int nbrImagesToDownload;
	
	private String seedUrl;
	private String pageRegex;
	private int pageRegexTruncateIndex;
	private String prependToPageUrl;
	private String imageRegex;
	private int imageRegexTruncateIndex;
	private String prependToImageUrl;

	/**
	 * 
	 * @param view - Parent view
	 * @param runType - Type of run, first or any later run
	 * @param imagesToDownload - The number of images to download
	 * @param linkTarget - Urlpackage for the links
	 * @param imageTarget - Urlpackage for the images
	 */
	public FetcherManager(ImageHandler imageHandler, int nbrImagesToDownload, String seedUrl,
			String pageRegex, int pageRegexTruncateIndex, String prependToPageUrl, String imageRegex,
			int imageRegexTruncateIndex, String prependToImageUrl) {
		Log.d(getClass().getSimpleName(), "Creating Fetchers \n");
		visitedUrls = new HashMap<String, Boolean>();
		imageUrlList = new LinkedList<String>();
		linkUrlList = new LinkedList<String>();
		imagefetchers = new ArrayList<ImageFetcher>();
		threadfetchers = new ArrayList<ThreadFetcher>();

		this.imageHandler = imageHandler;
		this.nbrImagesToDownload = nbrImagesToDownload;
		this.seedUrl = seedUrl;
		this.pageRegex = pageRegex;
		this.pageRegexTruncateIndex = pageRegexTruncateIndex;
		this.prependToPageUrl = prependToPageUrl;
		this.imageRegex = imageRegex;
		this.imageRegexTruncateIndex = imageRegexTruncateIndex;
		this.prependToImageUrl = prependToImageUrl;
		
		Viewer.tempDir.mkdirs();
		
		startFetchers();
	}

	@Override
	protected void onPreExecute() {
		
	}

	@Override
	public Void doInBackground(String... params) {
		if (!initialized) {
			initialized = true;
			startFetchers();
		}
		indexfetcher.runOneIteration();

		for (int i = 0; i < imagefetchers.size(); i++) {
			Log.d("FetcherManager", "ImageFetcher-" + i + " started");
			imagefetchers.get(i).start();
		}

		for (int i = 0; i < threadfetchers.size(); i++) {
			Log.d("FetcherManager", "ThreadFetcher-" + i + " started");
			threadfetchers.get(i).start();
		}
		
		if (indexfetcher == null) {
			initIndexFetcher();
		}
		indexfetcher.start();

		// Wait until images can be downloaded
		do {
			try {
				Thread.sleep(250);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} while (imageUrlList.size() == 0);
		return null;
	}

	@Override
	protected void onPostExecute(Void param) {
		
	}
	
	private void initIndexFetcher() {
		indexfetcher = new IndexFetcher(this, seedUrl, pageRegex, pageRegexTruncateIndex,
				prependToPageUrl, imageRegex, imageRegexTruncateIndex, prependToImageUrl);
		indexfetcher.setName("IndexFetcher");
		indexfetcher.setPriority(Process.THREAD_PRIORITY_BACKGROUND);
	}
	
	private void startFetchers() {
		initIndexFetcher();
		for (int i = 0; i < MAX_IMAGEFETCHERS; i++) {
			Log.d(getClass().getSimpleName(), "ImageFetcher-" + i + " created");
			ImageFetcher temp = new ImageFetcher(this, imageHandler);
			temp.setName("ImageFetcher-" + i);
			temp.setPriority(Process.THREAD_PRIORITY_BACKGROUND - 2
					* Process.THREAD_PRIORITY_LESS_FAVORABLE);
			imagefetchers.add(temp);
		}

		for (int i = 0; i < MAX_THREADFETCHERS; i++) {
			Log.d(getClass().getSimpleName(), "ThreadFetcher-" + i + " created");
			ThreadFetcher temp = new ThreadFetcher(this, imageRegex, imageRegexTruncateIndex,
					prependToImageUrl);
			temp.setName("ThreadFetcher-" + i);
			temp.setPriority(Process.THREAD_PRIORITY_BACKGROUND
					- Process.THREAD_PRIORITY_LESS_FAVORABLE);
			threadfetchers.add(temp);
		}
	}

	public void destroyFetchers() {
		initialized = false;
		
		for (int i = 0; i < imagefetchers.size(); i++) {
			imagefetchers.get(i).done();
			imagefetchers.remove(i);
			Log.d(getClass().getSimpleName(), "ImageFetcher-" + i + " destroyed");
		}
		for (int i = 0; i < threadfetchers.size(); i++) {
			threadfetchers.get(i).done();
			threadfetchers.remove(i);
			Log.d(getClass().getSimpleName(), "ThreadFetcher-" + i + " destroyed");
		}
		if (indexfetcher != null) {
			indexfetcher.done();
			indexfetcher = null;
		}
	}

	public void setFetchersPause(boolean pause) {
		for (int i = 0; i < imagefetchers.size(); i++) {
			imagefetchers.get(i).pause(pause);
			Log.d(getClass().getSimpleName(), "ImageFetcher-" + i + " pause = " + pause);
		}
		for (int i = 0; i < threadfetchers.size(); i++) {
			threadfetchers.get(i).pause(pause);
			Log.d(getClass().getSimpleName(), "ThreadFetcher-" + i + " pause = " + pause);
		}
		if (indexfetcher != null) {
			indexfetcher.pause(pause);
			Log.d(getClass().getSimpleName(), "IndexFetcher" + " pause = " + pause);
		}
	}

	public synchronized String getNextImageName() {
		if (imageUrlList.size() != 0) {
			String temp = imageUrlList.poll();
			Log.d(getClass().getSimpleName(), "Delivered next image-url " + temp);
			return temp;
		}
		return null;
	}

	public synchronized String getNextUrl() {
		if (linkUrlList.size() != 0 && nbrImagesToDownload > 0) {

			String temp = linkUrlList.poll();
			Log.d(getClass().getSimpleName(), "Delivered next link-url " + temp);
			Log.d(getClass().getSimpleName(), "Link-urls left: " + linkUrlList.size());
			nbrImagesToDownload--;
			return temp;
		}
		return null;
	}
	
	public ArrayList<Integer> getImageFetcherProgress() {
		ArrayList<Integer> progress = new ArrayList<Integer>(imagefetchers.size());
		for(ImageFetcher img : imagefetchers) {
			progress.add(img.getProgress());
		}
		return progress;
	}

	public synchronized void addImageUrl(String url) {
		if (!imageUrlList.contains(url) && visitedUrls.get(url) == null) {
			Log.d(getClass().getSimpleName(), "Added image-url  -  " + url);
			visitedUrls.put(url, true);
			imageUrlList.add(url);
		}
	}

	public synchronized void addLinkUrl(String url) {
		if (!linkUrlList.contains(url) && visitedUrls.get(url) == null) {
			Log.d(getClass().getSimpleName(), "Added link-url  -  " + url);
			visitedUrls.put(url, true);
			linkUrlList.add(url);
		}
	}

	public void downloadNewImages(int number) {
		nbrImagesToDownload = number;
	}

	public int getNbrImagesToDownload() {
		return nbrImagesToDownload;
	}

	public int getNbrImageLinks() {
		return imageUrlList.size();
	}

	public int getNbrUrlLinks() {
		return linkUrlList.size();
	}

}
